package com.qf.listener;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Component

public class Listener1 {
    @Autowired
    private RedisTemplate redisTemplate;
    @RabbitListener(queues = "test1")
    public void messageHandler(String msg, Channel channel, Message message) {

        try {
            //1.接收messageId,消息的唯一id
            String messageId = (String) message.getMessageProperties().getHeaders().get("spring_returned_message_correlation");

            //2.将消息的唯一id作为key使用redis的setnx命令，存入redis中，生存时间3秒
            if (redisTemplate.opsForValue().setIfAbsent(messageId,"0",3, TimeUnit.SECONDS)) {
                //3.接受消息，消费消息，处理业务
                System.out.println("=====这里是1号,消费消息，处理业务====" + msg);
                //4.消息处理完成后，返回给mq回执，处理成功
                //redisTemplate.opsForValue().set(messageId,"1",3,TimeUnit.SECONDS);
                //制造异常
                //int i = 1/0;
                /*
                 * 消费者发起成功通知
                 * 第一个参数: DeliveryTag,消息的唯一标识  channel+消息编号
                 * 第二个参数：是否开启批量处理 false:不开启批量
                 * 举个栗子： 假设我先发送三条消息deliveryTag分别是5、6、7，可它们都没有被确认，
                 *          当我发第四条消息此时deliveryTag为8，multiple设置为 true，会将5、6、7、8的消息全部进行确认。
                 */
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            }else {
                //这个消息redis中处理过，说明有业务处理，不能重复处理
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            }
        } catch (Exception e) {
            e.printStackTrace();
            /*
             * 返回失败通知
             * 第一个参数: DeliveryTag,消息的唯一标识  channel+消息编号
             * 第二个boolean true所有消费者都会拒绝这个消息，false代表只有当前消费者拒绝
             * 第三个boolean true消息接收失败重新回到原有队列中
             */
            try {
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }


    }

}
